// 1.
// 设计原则
// 单一职责（SRP）
// 最少知识原则（LKP）迪米特法则
// 开放-封闭 （OCP）

// new 操作符
const obj = Object.create(null)
Object.create = Object.create || function(obj){
  let F = function(){}
  F.prototype = obj
  return new F()
}
const objectFactory = function(){
  // 1
  const obj = new Object()
  // arguments [Dog,'']
  // ['']
  const constructor = [].shift.call(arguments)
  // constructor = [Dog,''].shift()
  // 2
  obj.__proto__ = constructor.prototype
  // 3.
  const ret = constructor.apply(obj,arguments)
  // return obj
  return typeof ret === 'object'?ret: obj
}

const Dog = function(a,b){
  this.name = name
  // return {
  //   name: a+b
  // }
}

const b = new Dog(1,2)
objectFactory(Dog,'')


// 原型模式
const Dog = function(){}
Dog.prototype.sound = ()=>{
  console.log('wang')
}
const makeSound = (animal)=>{
  animal.sound()
}
makeSound(new Dog())
// 单例模式
// 1
const Singleton = (name)=>{
  this.name = name
}
Singleton.instance = null
Singleton.prototype.getName = ()=>{
  console.log(this.name)
}
Singleton.getIntance = (name)=>{
  if(!this.instance){
    this.instance = new Singleton(name)
  }
  return this.instance
}
const a = Singleton.getIntance('a')
const b = Singleton.getIntance('b')
// a===b
// 2.
const createDiv = (function(){
  let instance
  const cd = function(html){
    if(instance) return instance
    this.html = html
    this.init()
    return instance = this
  }
  cd.prototype.init = ()=>{
    const div = document.createElement('div')
    div.innerHTML = this.html
    document.body.appendChild(div)
  }
  return cd
})()
const a = new createDiv('a')
const b = new createDiv('b')
// a===b ----> true

// 3.代理实现单例
const CreateDiv = function(html){
  this.html = html
  this.init()
}
CreateDiv.prototype.init = ()=>{
  const div = document.createElement('div')
  div.innerHTML = this.html
  document.body.appendChild(div)
}
const proxySingletonCreateDiv = (function(){
  let instance
  return function(html){
    if(!instance){
      instance = new CreateDiv(html)
    }
    return instance
  }
})()

const a = new proxySingletonCreateDiv('a')
const b = new proxySingletonCreateDiv('b')
// a===b

// 计算年终奖
function clacBound(performanceLeval,salary){
  // 策略 - 多种方式之间的互相替换
  if(performanceLeval === 'S'){
    return salary * 4
  }
  if(performanceLeval === 'A'){
    return salary * 3
  }
  if(performanceLeval === 'B'){
    return salary * 2
  }
}
// 策略
var strategies = {
  'S' :(salary)=>{
    return salary * 4
  },
  'A' :(salary)=>{
    return salary * 3
  },
  'B' :(salary)=>{
    return salary * 2
  }
}

function clacBounds(lv,salary){
  return strategies[lv](salary)
}
// 代理模式 - 替身
var Flower = function(){}
var xiaoming = {
  // 送
  sendFlower: function(target){
    var flower = new Flower()
    target.receiveFlower(flower)
  }
}
var B = {
  // 接受
  receiveFlower: function(flower){
    A.listenerGoodMood(function(){ //保护代理
      A.receiveFlower(flower)
    })
  }
}

var A = {
  receiveFlower: function(flower){
    console.log('收到')
  },
  listenerGoodMood: function(fn){
    setTimeout(function(){
      fn()
    },1000)
  }
}
xiaoming.sendFlower(B)


// 图片预加载
// 虚拟代理实现
var myImage = (function(){
  var imgNode = document.createElement('img')
  document.body.appendChild(imgNode)
  return {
    src: function(src){
      imgNode.src = src
    }
  }
})()

var proxyImage = (function(){
  var img = new Image
  img.onload = function(){
    myImage.src(this.src)
  }
  return {
    setSrc:function(src){
      myImage.src('http://loading.gif')
      img.src = src
    }
  }
})()

proxyImage.setSrc('http://xxx.png')


// 不使用代理图片预加载
var myImage = (function(){
  var imgNode = document.createElement('img')
  document.body.appendChild(imgNode)
  var img = new Image
  img.onload = function(){
    imgNode.src = img.src
  }
  return {
    setSrc: function(src){
      imgNode.src = 'http://loading.gif'
      img.src = src 
    }
  }
})()
myImage.setSrc('http://xxx.png')

// 单一原则
// 代理对象和本体对象都是函数
var myImage = (function(){
  var imgNode = document.createElement('img')
  document.body.appendChild(imgNode)
  return function(src){
    imgNode.src = src
  }
})()


var proxyImage = (function(){
  var img = new Image
  img.onload = function(){
    myImage(this.src)
  }
  return function(src){
    myImage('http://loading.gif')
    img.src = src
  }
  
})()
proxyImage('http://xxx.png')

var mult = function(){
  var a = 1
  for(var i = 0,l = arguments.length;i<l;i++){
    a = a * arguments[i]
  }
  return a
}

mult(1,2,3)

// 缓存代理
var proxyMult = (function(){
  var cache = {}
  return function(){
    var args = Array.prototype.join.call(arguments,',')
    if(args in cache){
      return cache[args]
    }
    cache[args] = mult.apply(this,arguments)
    // {
    //   '1,2,3': 6
    // }
    return  cache[args]
  }
})()

proxyMult(1,2,3)
proxyMult(1,2,3)

// 变体
// -- 防火墙
// --远程代理(签证)
// --保护代理(控制访问)
// --智能引用代理(访问次数,检查日志)
// --写时复制代理(浅拷贝和深拷贝)(性能问题)

var teml = {
  a: 1,
  b :{
    c: 2
    d:teml
  }
}
// 
teml.b.d = teml

// 循环引用
JSON.parse(JSON.stringify(teml))
// 递归
_.deepClone()

